{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XNWJ6JVGkOlf"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors. [Licensed under the Apache License, Version 2.0](#scrollTo=bPJq2qP2KE3u)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "fSlQ2vFzKGOY"
      },
      "outputs": [],
      "source": [
        "// #@title Licensed under the Apache License, Version 2.0 (the \"License\"); { display-mode: \"form\" }\n",
        "// Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "// you may not use this file except in compliance with the License.\n",
        "// You may obtain a copy of the License at\n",
        "//\n",
        "// https://www.apache.org/licenses/LICENSE-2.0\n",
        "//\n",
        "// Unless required by applicable law or agreed to in writing, software\n",
        "// distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "// See the License for the specific language governing permissions and\n",
        "// limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yfNdITLmJtX8"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/swift/tutorials/raw_tensorflow_operators\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org で表示</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/swift/tutorials/raw_tensorflow_operators.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab で実行</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/swift/tutorials/raw_tensorflow_operators.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub でソースを表示</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lONNcRalVUO9"
      },
      "source": [
        "# 未加工の TensorFlow 演算子\n",
        "\n",
        "TensorFlow を基に構築された Swift for TensorFlow の API 設計には、斬新なアプローチが採用されています。API は確立したライブラリから慎重に選択され、新しい言語イディオムと組み合わされています。つまり、すべての TensorFlow API が Swift API として使用できるわけではなく、API のキュレーションを進めるには時間と献身的な取り組みが必要です。とはいえ、お気に入りの TensorFlow 演算子が Swift で使用できなくても、悩むことはありません。TensorFlow Swift ライブラリには、`_Raw` 名前空間の下に、ほとんどの TensorFlow 演算子への透過的なアクセスが提供されています。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CYqNvcHxqg0Y"
      },
      "source": [
        "まず `TensorFlow` をインポートします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cVRrzjzFqee9"
      },
      "outputs": [],
      "source": [
        "import TensorFlow"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5vza91sR09r-"
      },
      "source": [
        "## 未加工の演算を呼び出す\n",
        "\n",
        "コード補完機能を使用して、`_Raw` 名前空間から必要な関数を見つけてください。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kZRlD4utdPuX"
      },
      "outputs": [],
      "source": [
        "_Raw.mul(Tensor([2.0, 3.0]), Tensor([5.0, 6.0]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iIgKg-ueVCy_"
      },
      "source": [
        "## 新しい乗算演算子を定義する\n",
        "\n",
        "乗算は、すでに演算子 `*` として `Tensor` に提供されていますが、`.*` という新しい名前を付けることにしましょう。Swift では、`extension` 宣言を使用して、メソッドや計算済みのプロパティを遡及的に既存の型に追加できます。\n",
        "\n",
        "では、extension を宣言して `.*` を `Tensor` に追加し、テンソルの `Scalar` 型が [`Numeric`](https://developer.apple.com/documentation/swift/numeric) に適合する場合に利用できるようにしましょう。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "BdH-yZBjTZNx"
      },
      "outputs": [],
      "source": [
        "infix operator .* : MultiplicationPrecedence\n",
        "\n",
        "extension Tensor where Scalar: Numeric {\n",
        "    static func .* (_ lhs: Tensor, _ rhs: Tensor) -> Tensor {\n",
        "        return _Raw.mul(lhs, rhs)\n",
        "    }\n",
        "}\n",
        "\n",
        "let x: Tensor<Double> = [[1.0, 2.0], [3.0, 4.0]]\n",
        "let y: Tensor<Double> = [[8.0, 7.0], [6.0, 5.0]]\n",
        "x .* y"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ucD5XZYYyzNe"
      },
      "source": [
        "## ラッピングされた関数の導関数を定義する\n",
        "\n",
        "未加工の TensorFlow 演算子に Swift API を定義できるだけでなく、Swift のファーストクラスの自動微分を使用できるように微分可能にすることもできます。\n",
        "\n",
        "`.*` を微分可能にするには、導関数で `@derivative` 属性を使用し、元の関数を `of:` ラベルの属性引数として指定します。`.*` 演算子は、汎用型の `Scalar` が `Numeric` に適合する場合に定義されるため、`Tensor<Scalar>` が `Differentiable` プロトコルに適合されるようにするには不足しています。型安全性を備える Swift では、`@differentiable` 属性に対して、`Scalar` が `TensorFlowFloatingPoint` プロトコルに適合しなければならないという一般制約を課すことが求められるため、`Tensor<Scalar>` は `Differentiable` に適合されるようになります。\n",
        "\n",
        "```swift\n",
        "@differentiable(where Scalar: TensorFlowFloatingPoint)\n",
        "```"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fDXS0h_YumcL"
      },
      "outputs": [],
      "source": [
        "infix operator .* : MultiplicationPrecedence\n",
        "\n",
        "extension Tensor where Scalar: Numeric {\n",
        "    @differentiable(where Scalar: TensorFlowFloatingPoint)\n",
        "    static func .* (_ lhs: Tensor,  _ rhs: Tensor) -> Tensor {\n",
        "        return _Raw.mul(lhs, rhs)\n",
        "    }\n",
        "}\n",
        "\n",
        "extension Tensor where Scalar : TensorFlowFloatingPoint { \n",
        "    @derivative(of: .*)\n",
        "    static func multiplyDerivative(\n",
        "        _ lhs: Tensor, _ rhs: Tensor\n",
        "    ) -> (value: Tensor, pullback: (Tensor) -> (Tensor, Tensor)) {\n",
        "        return (lhs * rhs, { v in\n",
        "            ((rhs * v).unbroadcasted(to: lhs.shape),\n",
        "            (lhs * v).unbroadcasted(to: rhs.shape))\n",
        "        })\n",
        "    }\n",
        "}\n",
        "\n",
        "// Now, we can take the derivative of a function that calls `.*` that we just defined.\n",
        "gradient(at: x, y) { x, y in\n",
        "    (x .* y).sum()\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l7kae5o1VKnu"
      },
      "source": [
        "## その他の例"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "v92FrXpCSuLT"
      },
      "outputs": [],
      "source": [
        "let matrix = Tensor<Float>([[1, 2], [3, 4]])\n",
        "\n",
        "print(_Raw.matMul(matrix, matrix, transposeA: true, transposeB: true))\n",
        "print(_Raw.matMul(matrix, matrix, transposeA: true, transposeB: false))\n",
        "print(_Raw.matMul(matrix, matrix, transposeA: false, transposeB: true))\n",
        "print(_Raw.matMul(matrix, matrix, transposeA: false, transposeB: false))"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "raw_tensorflow_operators.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Swift",
      "name": "swift"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
